package com.sd365.permission.centre.service;

import com.sd365.common.core.annotation.mybatis.Pagination;
import com.sd365.common.core.annotation.stuffer.CommonFieldStuffer;
import com.sd365.common.core.annotation.stuffer.MethodTypeEnum;
import com.sd365.common.core.common.api.CommonPage;
import com.sd365.permission.centre.entity.Node;
import com.sd365.permission.centre.entity.Role;
import com.sd365.permission.centre.pojo.dto.*;
import com.sd365.permission.centre.pojo.query.RoleQuery;
import com.sd365.permission.centre.pojo.query.UserQuery;
import com.sd365.permission.centre.pojo.vo.RoleCompanyVO;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * @Class RoleService
 * @Description 优化代码和修复bug，包含了redis初始化角色对应资源（应用于鉴权服务）以及role增删改查方法
 * @Author Administrator
 * @Date 2022-9-30  14:48
 * @version 1.0.0
 */
//@CacheConfig(cacheNames = "RoleService")
public interface RoleService {
    /**
     *  状态标记
     */
    byte INITIALIZE_STATUS_VALUE=1;
    /**
     * 版本标记
     */
    long INITIALIZE_VERSION_VALUE=1;

    /**
     *  初始化角色对应的资源列表，通用用户传入一个new Role获取所有的角色
     *  然后内部在对每个角色的资源做缓存，其他模块可以快速根据角色id取得资源列表
     *  重构增加了一个没有查询到数据的异常处理
     *  TODO 该方法实现较为混乱，效率低下有待重构
     * @param role 角色 一般是new Role 没有赋值
     * @return true 成功 false失败
     */
    Boolean loadRoleResource2Cache(@NotNull Role role);
    /**
     * 批量插入，插入前先删除原来的角色和资源的关系
     * @param: 前端选择的角色资源列表
     * @return: 成功ture 失败 false
     */
    @Transactional
    Boolean assignResource(@NotNull @Valid RoleResourceDTO roleResourceDTO);

    /**
     * 删除原来的用户 插入行的用户，新的用户以勾选的用户为准
     * @param: 勾选的用户列表
     * @return: 成功true 否则失败
     */
    @Transactional
    Boolean assignUser(@NotNull @Valid UserRoleDTO userRoleDTO);

    /**
     * 查询角色所拥有的所有资源
     * @return Node 角色所拥有的资源，这里构建为node而不是resource是比较奇怪的做法
     * 可能是开发人员考虑树的节点上存在公司，资源等等所以统一采用node
     */
    List<Node> queryResourceByRoleId(@NotNull long roleId);

    /**
     * 查询公司节点
     * @return Node 公司节点信息
     */
    List<Node> selectCompany();
    /**
     * 验证是否已经存在角色
     * @return true成功 false失败
     */
    boolean haveRole(@NotNull RoleDTO roleDTO);

    /** 增加角色
     * @param: 角色DTO
     * @return: 成功则true
     */
    Boolean add(@NotNull @Valid RoleDTO roleDTO);

    /**
     * 删除角色，注意如果角色被使用不可以删除
     * @param id 角色id
     * @param version 版本 使用乐观锁后改参数实际没有意义
     * @return true成功 false失败，如果存在关联则抛出异常
     */
    Boolean remove(@NotNull Long id, @NotNull Long version);
    /**
     * 修改角色
     * @param roleDTO 角色记录数据
     * @return true成功 false失败
     */
    RoleDTO modify(@NotNull @Valid RoleDTO roleDTO);

    /**
     * 查询角色 依据 UI的查询区条件
     * @param roleQuery  查询条件 多个条件组合
     * @return 角色列表
     */
    @Pagination
    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    CommonPage<RoleDTO> commonQuery(@NotNull  RoleQuery roleQuery);

    /**
     * 根据id找到对应的角色
     * @param id  角色id
     * @return 返回角色RoleDTO
     */
    RoleDTO queryById(@NotNull Long id);

    /**
     * 复制一条和RoleDTO 一样的记录并且将值返回前端
     * @param id  选中的角色id
     * @return 角色对象
     */
    RoleDTO copy(@NotNull Long id);
    /**
     *  批量删除 角色注意
     * @param roleDTOS
     * @return
     */
    @Transactional
    Boolean batchRemove(@NotEmpty @Valid RoleDTO[] roleDTOS);

    /**
     * 角色界面绑定角色到相应的用户，此方法查找系统用户显示在对话框
     * @param userQuery 查询条件
     * @return 用户列表 重构为 CommonPage对象
     */
    @Pagination
    CommonPage<UserDTO> commonQueryUser(@NotNull UserQuery userQuery);

    /**
     *  查询某一个用户所有用的角色
     * @param id
     * @return
     */
    RoleDTO queryUserResource(@NotNull Long id);

    /**
     * 通过角色id获取关联的授权公司列表
     * @param id  角色id
     * @return RoleCompanyVO  角色所拥有的公司 TODO 这里支持1对多公司
     */
    RoleCompanyVO queryRoleCompanyById(@NotNull Long id);

    /**
     * 修改角色id关联的授权公司列表
     * @param roleCompanyDTO
     * @return true成功 false失败
     */
    @Transactional
    Boolean modifyRoleCompany(@NotNull @Valid  RoleCompanyDTO roleCompanyDTO);
}
